Implementation: The Templates:

 

The template approach to creating pseudoPODs turned out to be less efficient that the macro approach, so should be used only by those that truly hate macros.

pseudoPODs created by templates behave the same as pseudoPODs created by macros, but the limitations of templates differ from the limitations of macros, so there are some differences in the implementation code.

See file pseudoPOD.h for the code for the template approach (www.dlmowery.com/pseudoPOD/pseudoPOD.h).

## Token Pasting:

Macros can create new names by ## pasting two names together, but templates cannot.  Consequently:

1) templates can't call the get() & set() routines by combining the ep pointer to the enclosing class with the names of the get() & set() routines, because that would require combining "get_" or "set_" with the name of the variable, so the template nested class must have 3 pointers - ep that points to the enclosing class, ep_get that points to the get() routine, and ep_set that points to the set() routine.  When a pseudoPOD created by a template wants to call get() or set(), it combines the ep pointer to the enclosing class with either the ep_get pointer or the ep_set pointer in a pointer-to-member style call, i.e.:

(ep->*ep_get)();     or      (ep->*ep_set)();

2) There's no way of deducing the group of operators to support from the data type, so there's another template with the suffix "_f" for floats and doubles.

3) There's no way of creating the name_value variable that holds the current value of the pseudoPOD in the enclosing class, so the coder has to do it manually, with another line of code.

4) For arrays there's no way of defining the const static variable that holds the number of elements in the array, so that too is left to the coder.

Array Index Calculation Limitation:

There's no way of getting the name of the array into the template's class definition, so no way of calculating the array index by using the address of the [0]th element of the array, so the template nested class adds an integer to hold the index, which is initialized by additional code in the constructor() of the enclosing class.

Befriending Limitation:

Once upon a time it was possible for a class defined within a template to declare a class specified in one of the template's arguments to be a friend, but the rules have changed, and that is no longer possible.  Since the enclosing class has to initialize the ep, ep_set, & ep_get pointers, and the nested class cannot declare it a friend, I have to leave these members public, exposing them to accidental corruption by code outside the enclosing class.  To be fair, the probability of accidentally typing fred.int1.ep when one intended to type fred.int1 is low.

Read Only & Write Only Limitation:

Since the enclosing class is not a friend, making the pseudoPOD's read or write functions private means that code in the enclosing class cannot read or write the pseudoPOD normally, using "int    1", but instead must call the get_int1() or set_int1() functions.

 

There are three main templates, one each for integers, floats, and pointers, which are named ppodt_i(), ppodt_f(), and ppodt_p().  ppodt_f() is used for float and double, ppodt_p() is used for pointers, and ppodt_i() is used for all other data types, including int, long, char, bool, etc.

Read only members use three more templates, named ppodt_i_ro(), ppodt_f_ro(), and ppodt_p_ro().

Write only members use three more templates, named ppodt_i_wo(), ppodt_f_wo(), and ppodt_p_wo().

Arrays use an additional set of 9 more templates, whose names are identical to the preceding, except that "_array" is added, as in ppodt_array_i().